#version 450

//enable #include
#extension GL_GOOGLE_include_directive : enable
#extension GL_EXT_nonuniform_qualifier : require

#include "PBRCommon.h"


layout (input_attachment_index = 0, binding = 0) uniform subpassInput samplerAlbedo;
layout (input_attachment_index = 1, binding = 1) uniform subpassInput samplerposition;
layout (input_attachment_index = 2, binding = 2) uniform subpassInput samplerNormal;


layout (location = 0) out vec4 outColor;

layout (push_constant) uniform SSpotLight
{
    vec3 viewPos; 
    float Padding;
    vec3 position;
    float Shadowbias;
    vec3 colorWithIntensity; //light color multiplied by intensity 
    float Padding2;
    mat4 LightVP;  
} SpotLight;

layout (set=1, binding = 0) uniform sampler2D SpotLightShadowMap;


void main() 
{
	// Read G-Buffer values from previous sub pass
	vec3 normal = subpassLoad(samplerNormal).rgb;

    if(normal==vec3(0.0))
    {
        //for unlit meshes
        discard;
    }

	vec3 fragPos = subpassLoad(samplerposition).rgb;
	vec3 albedo = subpassLoad(samplerAlbedo).rgb;
	
    float ao=subpassLoad(samplerAlbedo).a;
	float metallic=subpassLoad(samplerposition).a;
	float roughness=subpassLoad(samplerNormal).a;

    vec3 V=normalize(SpotLight.viewPos-fragPos);
	vec3 N=normal;
    //base reflectance
    vec3 F0=vec3(0.04);
    F0=mix(F0,albedo,metallic);

    vec3 Sum=vec3(0.0);


    //light by spot light
    //for(int SpotLightIndex=0;SpotLightIndex<ubo.SpotLightNum;SpotLightIndex++)
    {
        vec4 UnnormalizedLightSpacePosition=SpotLight.LightVP * vec4(fragPos,1);
        vec3 LightSpacePosition=UnnormalizedLightSpacePosition.xyz / UnnormalizedLightSpacePosition.w;
        
        vec2 ShadowMapUV= LightSpacePosition.xy *0.5 +0.5;

        //valid area of shadow map should be a circle,abandon piexl out of circle
        vec2 OffsetToCenter=ShadowMapUV-0.5;
        if(OffsetToCenter.x*OffsetToCenter.x +OffsetToCenter.y*OffsetToCenter.y> 0.5*0.5)
        {
            discard;
        }

        float ShadowMapDepth= texture(SpotLightShadowMap,ShadowMapUV).r +SpotLight.Shadowbias;

       

        float Distance=length(SpotLight.position-fragPos);
        if(Distance>ShadowMapDepth)
        {
            discard;
        }                                                                                                                         

        vec3 LightDir=normalize(SpotLight.position-fragPos);
        vec3 Half=normalize(V+LightDir);

        //calculate radiance
        //float Distance=length(SpotLight.position-fragPos);
        float Attenuation=1.0/(Distance*Distance);
        vec3  radiance=SpotLight.colorWithIntensity*Attenuation;

        //cook-torrance BRDF
        float NDF=DistributionGGX(N,Half,roughness);
        float G=GeometrySmith(N, V, LightDir, roughness);   
        vec3  F=fresnelSchlick(max(dot(Half, V), 0.0), F0);

        vec3 numerator=NDF*G*F;
        float denominator=4.0 * max(dot(N, V), 0.0) * max(dot(N, LightDir), 0.0) + 0.0001; // + 0.0001 to prevent divide by zero
        vec3 specular= numerator/denominator;

        vec3 Ks=F;
        vec3 Kd=vec3(1.0)-Ks; 
        Kd*=1.0-metallic;

        float NdotL=max(dot(N,LightDir),0.0);
        
        Sum+=(Kd*albedo/PI +specular)* radiance * NdotL;
    }

    // HDR tonemapping
    vec3 Color = Sum / (Sum + vec3(1.0));

    outColor=vec4(Color,1.0);

}